# 点亮战争迷雾[200分]

# 题目内容

有一张二叉树地图,每一个节点都被战争迷雾所覆盖。在二叉树节点上插上一个侦察守卫,可以照亮该节点自身以及它的父节点和它的子节点的战争迷雾。在每个节点上插上侦察守卫的成本并不一样,用 $cost[i]$ 表示节点 $i$ 上的成本,每个节点的成本是正整数。

要求:

  • 所有的战争迷雾都被驱散。
  • 所花费的总成本最小。

补充说明:

  • 单个节点的成本,$1 \le cost[i] \le 100$;
  • 节点总数量 $\le 1000$。

# 输入描述

一行,一个层序遍历字符串(含首尾圆括号),空节点用 # 表示,例如 (5,1,10,2,8,#,3)

# 输出描述

输出最小的总费用。

# 样例

# 样例 1

输入

5,1,10,2,8,#,3
1

输出

4
1

说明:

树结构图:

              1(5)
            /   \
           2(1)  3(10)
          / \     \
         4(2) 5(8) 6(3)
1
2
3
4
5

最优方案:在节点 2(成本 1)和节点 6(成本 3)插上侦察守卫,总成本 4。节点 2 覆盖 2,1,4,5;节点 6 覆盖 6,3;所有节点均被覆盖。

# 样例 2

输入

3,1,1
1

输出

2
1

说明:

树结构:

             1(3)
            /   \
           2(1)  3(1)
1
2
3

方案一:在节点 1 插上侦察守卫,可照亮所有地图,成本是 3。方案二:在节点 2 和节点 3 插上侦察守卫,可照亮所有地图,成本是 $1+1=2$。因此,最低成本的方案是方案二,返回值是 2。

# 代码

const readline = require('readline');
const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout,
});

rl.on('line', (input) => {
    const arr = input.split(',').map(v => {
        if (v !== '#') {
            return Number(v); 
        } else {
            return '#';
        }
    })
    function buildTree() {
        const root = {cost: arr[0], left: null, right: null};
        let i=1;
        let queue = [root];
        while(queue.length && i<arr.length) {
            let node = queue.shift();
            if (i<arr.length && arr[i] !== '#') {
                node.left = {cost: arr[i], left: null, right: null}
                queue.push(node.left);
            }
            i++;
            if (i<arr.length && arr[i] !== '#') {
                node.right = {cost: arr[i], left: null, right: null}
                queue.push(node.right);
            }
            i++;
        }
        return root;
    }
    const root = buildTree();
    // dp0 自己亮+儿子最小成本+父亲最小成本
    // dp1 自己被儿子照亮。左儿子一定亮+右儿子。左儿子+右儿子一定亮
    // dp2 自己被父亲照亮。左儿子父亲不亮+右儿子父亲不亮
    const dfs = (node) => {
        if (!node) return [Infinity, 0, 0]; //我不能买灯(太贵了选不上我),但我不需要被照(免费),我不需要等爹照(免费)
        const [cost1, l1, l2] = dfs(node.left);
        const [cost2, r1, r2] = dfs(node.right);
        const self = node.cost + Math.min(cost1, l1, l2) + Math.min(cost2, r1, r2);
        const dad = Math.min(cost1, l1) + Math.min(cost2, r1);// 儿子不是被父亲照亮
        const left = cost1 + Math.min(cost2, r1);// 左儿子一定亮+右儿子不被父亲照亮(自己没亮)
        const right = cost2 + Math.min(cost1, l1);
        const son = Math.min(left, right);
        return [self, son, dad];
    }
    const [dp0, dp1, dp2] = dfs(root);
    console.log(Math.min(dp0, dp1));
    
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52